package algebra.query;

import java.util.Map;
import java.util.Set;

import utils.exception.SyntaxParsingException;

import algebra.query.pd.ProjDesc;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import entities.concept.Concept;
import entities.role.Role;

public class ParamterizedObjectQuery extends ObjectQuery {

	private ParamterizedObjectQuery(Concept c, ProjDesc pd) {
		// check c first
		super(c, pd);
	}

	// make a query parameterized
	public static ParamterizedObjectQuery getParameterizedObjectQuery(
			ObjectQuery oq) {
		Concept c = oq.getC();
		return new ParamterizedObjectQuery(c.makeParameterized(), oq.getPd());
	}

	public static ObjectQuery initParameterizedObjectQuery(ObjectQuery oq,
			String json) {
		try {
			Concept newc = setValue(oq.getC(), json);
			return new ObjectQuery(newc, oq.getPd());
		} catch (SyntaxParsingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// format: if one param: give a value
	// if more than one param: supply a map in JSON format:{f:0}
	private static Concept setValue(Concept c, String json)
			throws SyntaxParsingException {
		if (!c.isParameterized()) {
			return c;
		}
		Concept ret = c;
		Set<Role> fs = c.extractFeatures();
		JsonParser jp = new JsonParser();
		JsonElement input = jp.parse(json);
		if (input.isJsonNull()) {
			throw new SyntaxParsingException("The parameters should "
					+ "be initialized as follow:" + "\n {f:2, g:4}");
		} else if (input.isJsonObject()) {
			// a json object
			JsonObject obj = (JsonObject) input;
			for (Map.Entry<String, JsonElement> e : obj.entrySet()) {
				if (!e.getValue().isJsonPrimitive()) {
					// only accept primitive values
					continue;
				}
				Role rf = Role.createRoleAsIs(e.getKey());
				if (fs.contains(rf)) {
					// set value of this feature
					ret = ret.initParameters(rf, e.getValue().getAsString());
				}
			}
		}
		return ret;
	}

}
